/*
 * @Author: Swance
 * @Date: 2023-12-28
 * @Description: 文本插件
 */

import { fabric } from 'fabric';
import { IEditor } from '@/types/global';
import { v4 as uuid } from 'uuid';
import FontFaceObserver from 'fontfaceobserver';
import { BoardSyncEvent, JsonOption, textFamilyList } from '@/utils/Const.ts';

class TextBoxPlugin {
  canvas: fabric.Canvas;
  editor: IEditor;
  textMode: boolean;
  static pluginName = 'TextBoxPlugin';
  static apis: string[] = [
    'setTextMode',
    'setTextSize',
    'setTextColor',
    'setTextAlign',
    'setTextFontFamily',
    'setTextLineHeight',
    'setTextBold',
    'setTextUnderLine',
    'setTextLinethrough',
    'setTextItalic',
  ];

  constructor(canvas: fabric.Canvas, editor: IEditor) {
    this.canvas = canvas;
    this.editor = editor;
    this.textMode = false;
    this.init();
  }

  init() {
    const { canvas } = this;
    let fontFamily: FontFaceObserver;
    textFamilyList.forEach((item) => {
      fontFamily = new FontFaceObserver(item.typeName);
      // 加载完成后执行
      fontFamily
        .load()
        // 加载成功
        .then(() => {
          console.info('字体预加载成功');
        })
        // 加载失败
        .catch((e) => {
          console.log(e);
          console.error('字体预加载失败');
        });
    });
    canvas.on('mouse:down', (e) => {
      if (!this.textMode) return;
      //取消画布中所有对象的选中状态
      canvas.discardActiveObject();
      let x = 200;
      let y = 200;
      if (e.pointer) {
        x = e.pointer.x;
        y = e.pointer.y;
      }
      const text = new fabric.Textbox('', {
        top: y,
        left: x,
        fontSize: 18,
        originY: 'center',
        lineHeight: 1,
        lock: false,
        textAlign: 'left',
        stroke: 'rgba(0, 0, 0, 1)',
        fill: 'rgba(0, 0, 0, 1)',
        fontFamily: '思源黑体',
        perPixelTargetFind: true,
        id: uuid(),
        erasable: false, // 不允许擦拭
        strokeUniform: true,
      });
      canvas.add(text);
      canvas.setActiveObject(text);
      text.enterEditing();
    });
  }

  getActiveTextObject() {
    const activeObject = this.canvas.getActiveObject();
    if (activeObject && activeObject.type === 'textbox') {
      return activeObject;
    }
    return null;
  }

  setTextMode(params: boolean) {
    this.textMode = params;
    if (this.textMode) {
      this.canvas.selection = false;
      this.canvas.getObjects().forEach((obj) => {
        // 禁止选中画布元素
        obj.selectable = false;
        // 隐藏画布元素的控制角，使其旋转、缩放
        obj.hasControls = false;
        obj.evented = false;
      });
    } else {
      const textObjects = this.canvas.getObjects('textbox');
      const list = textObjects.filter((item) => {
        return item.text === '';
      });
      this.canvas.remove(...list);
    }
  }

  // 设置文字字体
  setTextFontFamily(family: string) {
    const activeObject = this.getActiveTextObject();
    if (!activeObject) return;
    // 监听当前要设置的字体加载情况
    const fontFamily = new FontFaceObserver(family);
    // 加载完成后执行
    fontFamily
      .load()
      // 加载成功
      .then(() => {
        const target = this.canvas.getActiveObject();
        if (target) {
          const oldElementJson = target.toJSON(JsonOption);
          activeObject.set('fontFamily', family);
          const newElementJson = target.toJSON(JsonOption);
          this.editor.emit(BoardSyncEvent.UPDATE, {
            isNewAction: true,
            oldElements: [oldElementJson],
            newElements: [newElementJson],
          });
          this.canvas.requestRenderAll();
        }
      })
      // 加载失败
      .catch((e) => {
        console.log(e);
        console.error('字体加载失败');
      });
  }

  // 设置文字大小
  setTextSize(fontSize: number) {
    const activeObject = this.getActiveTextObject();
    if (!activeObject) return;
    const oldElementJson = activeObject.toJSON(JsonOption);
    activeObject.fontSize = fontSize;
    const newElementJson = activeObject.toJSON(JsonOption);
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [oldElementJson],
      newElements: [newElementJson],
    });
    this.canvas.requestRenderAll();
  }

  // 设置文字颜色
  setTextColor(color: string) {
    const activeObject = this.getActiveTextObject();
    if (!activeObject) return;
    const oldElementJson = activeObject.toJSON(JsonOption);
    activeObject.fill = color;
    activeObject.stroke = color;
    activeObject.dirty = true;
    const newElementJson = activeObject.toJSON(JsonOption);
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [oldElementJson],
      newElements: [newElementJson],
    });
    this.canvas.requestRenderAll();
  }

  // 设置文字对齐
  setTextAlign(type: string) {
    const activeObject = this.getActiveTextObject();
    if (!activeObject) return;
    const oldElementJson = activeObject.toJSON(JsonOption);
    activeObject.textAlign = type;
    const newElementJson = activeObject.toJSON(JsonOption);
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [oldElementJson],
      newElements: [newElementJson],
    });
    this.canvas.requestRenderAll();
  }

  // 设置文字加粗
  setTextBold(bool: boolean) {
    const activeObject = this.getActiveTextObject();
    if (!activeObject) return;
    const oldElementJson = activeObject.toJSON(JsonOption);
    activeObject.fontWeight = bool ? 'bold' : 'normal';
    const newElementJson = activeObject.toJSON(JsonOption);
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [oldElementJson],
      newElements: [newElementJson],
    });
    this.canvas.requestRenderAll();
  }

  // 设置下划线
  setTextUnderLine(bool: boolean) {
    const activeObject = this.getActiveTextObject();
    if (!activeObject) return;
    const oldElementJson = activeObject.toJSON(JsonOption);
    activeObject.underline = bool;
    activeObject.dirty = true;
    const newElementJson = activeObject.toJSON(JsonOption);
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [oldElementJson],
      newElements: [newElementJson],
    });
    this.canvas.requestRenderAll();
  }

  // 设置删除线
  setTextLinethrough(bool: boolean) {
    const activeObject = this.getActiveTextObject();
    if (!activeObject) return;
    const oldElementJson = activeObject.toJSON(JsonOption);
    activeObject.linethrough = bool;
    activeObject.dirty = true;
    const newElementJson = activeObject.toJSON(JsonOption);
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [oldElementJson],
      newElements: [newElementJson],
    });
    this.canvas.requestRenderAll();
  }

  // 设置斜体
  setTextItalic(bool: boolean) {
    const activeObject = this.getActiveTextObject();
    if (!activeObject) return;
    const oldElementJson = activeObject.toJSON(JsonOption);
    activeObject.fontStyle = bool ? 'italic' : 'normal';
    const newElementJson = activeObject.toJSON(JsonOption);
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [oldElementJson],
      newElements: [newElementJson],
    });
    this.canvas.requestRenderAll();
  }

  // 设置文字行高
  setTextLineHeight(height: number) {
    const activeObject = this.getActiveTextObject();
    if (!activeObject) return;
    const oldElementJson = activeObject.toJSON(JsonOption);
    activeObject.lineHeight = height;
    const newElementJson = activeObject.toJSON(JsonOption);
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [oldElementJson],
      newElements: [newElementJson],
    });
    this.canvas.requestRenderAll();
  }
}
export default TextBoxPlugin;
